package com.ljw.spring.annotation.ext;

import com.ljw.spring.annotation.bean.Desk;
import com.ljw.spring.annotation.bean.User;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * @FileName ExtConfig
 * @Description TODO spring的扩展配置类
 * 1. BeanPostProcessor接口：bean的后置（bean初始化方法执行前后）处理器
 *      bean初始化方法执行前后进行一些逻辑工作：
 *                  postProcessBeforeInitialization()方法：bean初始化方法执行前 执行此方法
 *                  postProcessAfterInitialization()方法：bean初始化方法执行后 执行此方法
 * 2. BeanFactoryPostProcessor 接口： BeanFactory的后置处理器。
 *      实现该接口，重写方法postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
 *      执行时机：所有的bean定义信息被加载到BeanFactory，但是还没实例化的时候。
 * 3. BeanDefinitionRegistryPostProcessor接口：方法postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
 *      执行时机：所有的bean定义信息被加载到BeanFactory，但是还没实例化的时候，
 *      在BeanFactoryPostProcessor前执行，
 *      可以利用BeanDefinitionRegistryPostProcessor向IOC添加额外组件。
 *
 * 4. ApplicationListener接口:监听ioc容器中发布的事件，完成事件驱动开发
 *      ApplicationListener<E extends ApplicationEvent>：监听ApplicationEvent及其子类事件
 *      如何监听我们的自定义事件：
 *          （1）自定义事件类xxxEvent，继承ApplicationEvent
 *          （2）自定义监听器类，实现接口ApplicationListener，重写方法onApplicationEvent(xxxEvent event),
 *                  方法参数为我们的自定义事件类。
 *                  将自定义监听器类注册进入IOC容器[@Component]，这样当IOC容器发布我们的自定义事件时，就能自动监听到我们的自定义事件
 *               a. 用注解@EventListener代替上面的监听器类， 可用于任意类【类不必实现接口ApplicationListener】的方法上【方法参数是自定义事件】，
 *                  且监听功能上比上面的监听器类先监听到同类事件
 *                  @EventListener
                    public void listener1(MyApplicationEvent event){...}
 *          (3) IOC容器发布事件：
 *              User user = context.getBean(User.class);//事件源
                MyApplicationEvent event = new MyApplicationEvent(user);
                context.publishEvent(event);
 *5. 自定义组件想要使用spring底层的组件（如ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware,MessageSourceAware等等）：
 *                  只需要自定义组件实现xxxAware接口，重写方法，则自定义组件在创建实例对象时，就会自动调用重写的方法注入相关spring底层组件。
 *                  如我的自定义类Boat中自动注入spring底层组件：ApplicationContext组件
 *                  自定义类Computer中自动注入spring底层组件：ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware,MessageSourceAware
 *                  xxxAware的功能是由xxxProcessor完成的，如ApplicationContextAware===》ApplicationContextAwareProcessor
 *
 *
 *  向IOC容器注册bean ：
 * 4. 接口BeanDefinitionRegistry，手动注册bean：
 *      调用方法BeanDefinitionRegistry.registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
 * 5. ImportSelector接口：组团导入组件bean，实现ImportSelector接口，重写方法selectImports()：返回需要导入的组件的 全类名数组
 *      class MyImportSelector implements ImportSelector
 *      配置类注解:@Import(value = {Color.class, Car.class, MyImportSelector.class})：向IOC容器中组团导入组件
 * 6. ImportBeanDefinitionRegistrar接口：
 *      手动注册bean：实现接口ImportBeanDefinitionRegistrar，重写方法registerBeanDefinitions():方法内用BeanDefinitionRegistry手动注册bean
 *      class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor
 *      配置类注解:@Import(value = {Color.class, Car.class, MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
 * 7. 实现FactoryBean接口，重写方法getObject()注册组件bean【需要在配置类中用@Bean注册FactoryBean接口的实现类】
 * @Author ljw
 * @Date 2021/2/4 1:25
 * @Version 1.0
 */
//@EnableAsync //开启异步执行功能   需在方法上添加注解@Async
@ComponentScan(basePackages = {"com.ljw.spring.annotation.ext"})
@Configuration
public class ExtConfig {

    @Bean(value = {"user"})
    public User getUser(){
        return new User();
    }


}
